package com.rfid.project.service;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.domain.Sort.Direction;

import biz.util.*;

import com.rfid.project.model.*;
import com.rfid.project.dao.*;
import com.rfid.project.exception.CannotUpdateException;
import com.mysema.query.BooleanBuilder;

import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

@Service
@Transactional
public class ProjectTaskDelayApplyService {

	@Autowired
	private ProjectTaskDelayApplyDao projectTaskDelayApplyDao;

	private QProjectTaskDelayApply $ = QProjectTaskDelayApply.projectTaskDelayApply;

	private QProjectTask $_projectTask = QProjectTask.projectTask;

	private ProjectTaskDao projectTaskDao;

	@Autowired
	private ProjectTaskPersonDao projetTaskPersonDao;

	private QProjectTaskPerson $_projectTaskPerson = QProjectTaskPerson.projectTaskPerson;

	@Autowired
	public void setProjetTaskPersonDao(ProjectTaskPersonDao projetTaskPersonDao) {
		this.projetTaskPersonDao = projetTaskPersonDao;
	}
	
	@Autowired
	private ProjectMemberDao projectMemberDao;

	private QProjectMember $_projectMember = QProjectMember.projectMember;

	@Autowired
	public void setProjectMemberDao(ProjectMemberDao projectMemberDao) {
		this.projectMemberDao = projectMemberDao;
	}

	@Autowired
	public void setProjectTaskDao(ProjectTaskDao projectTaskDao) {
		this.projectTaskDao = projectTaskDao;
	}

	@Autowired
	public void setProjectTaskDelayApplyDao(
			ProjectTaskDelayApplyDao projectTaskDelayApplyDao) {
		this.projectTaskDelayApplyDao = projectTaskDelayApplyDao;
	}

	public List<ProjectTaskDelayApply> findAll() {
		return ListUtil.toList(projectTaskDelayApplyDao.findAll());
	}

	public List<ProjectTaskDelayApply> findAll(Long applyPersonId,
			String applyReason, Long checkPersonId, String checkComment,
			Date applyTimeBegin, Date applyTimeEnd, Date checkTimeBegin,
			Date checkTimeEnd, String status, Date originalPlanFinishDateBegin,
			Date originalPlanFinishDateEnd, Date targetPlanFinishDateBegin,
			Date targetPlanFinishDateEnd, Long projectTaskId,
			String orderByAttribute) {
		BooleanBuilder condition = new BooleanBuilder();

		if (IdUtil.isNotEmpty(applyPersonId)) {
			condition.and($.applyPerson.id.eq(applyPersonId));
		}

		if (StringUtil.isNotEmpty(applyReason)) {
			condition.and($.applyReason.contains(applyReason));
		}

		if (IdUtil.isNotEmpty(checkPersonId)) {
			condition.and($.checkPerson.id.eq(checkPersonId));
		}

		if (StringUtil.isNotEmpty(checkComment)) {
			condition.and($.checkComment.contains(checkComment));
		}

		if (applyTimeBegin != null) {
			condition.and($.applyTime.after(applyTimeBegin));
		}

		if (applyTimeEnd != null) {
			condition.and($.applyTime.before(applyTimeEnd));
		}

		if (checkTimeBegin != null) {
			condition.and($.checkTime.after(checkTimeBegin));
		}

		if (checkTimeEnd != null) {
			condition.and($.checkTime.before(checkTimeEnd));
		}

		if (StringUtil.isNotEmpty(status)) {
			condition.and($.status.contains(status));
		}

		if (originalPlanFinishDateBegin != null) {
			condition.and($.originalPlanFinishDate
					.after(originalPlanFinishDateBegin));
		}

		if (originalPlanFinishDateEnd != null) {
			condition.and($.originalPlanFinishDate
					.before(originalPlanFinishDateEnd));
		}

		if (targetPlanFinishDateBegin != null) {
			condition.and($.targetPlanFinishDate
					.after(targetPlanFinishDateBegin));
		}

		if (targetPlanFinishDateEnd != null) {
			condition.and($.targetPlanFinishDate
					.before(targetPlanFinishDateEnd));
		}

		if (IdUtil.isNotEmpty(projectTaskId)) {
			condition.and($.projectTaskPerson.projectTask.id.eq(projectTaskId));
		}

		return ListUtil.toList(projectTaskDelayApplyDao.findAll(condition));
	}

	public Page<ProjectTaskDelayApply> findAll(Long projectId, Long projetTaskPersonId,
			Long applyPersonId, String applyReason, Long checkPersonId,
			String checkComment, Date applyTimeBegin, Date applyTimeEnd,
			Date checkTimeBegin, Date checkTimeEnd, String status,
			Date originalPlanFinishDateBegin, Date originalPlanFinishDateEnd,
			Date targetPlanFinishDateBegin, Date targetPlanFinishDateEnd,
			Long projectTaskId, int pageNumber, int pageSize,
			String sortAttribute, String orderDirection) {
		BooleanBuilder condition = new BooleanBuilder();

		if (IdUtil.isNotEmpty(projectId)) {
			BooleanBuilder der = new BooleanBuilder();
			der.and($_projectTask.project.id.eq(projectId));
			condition.and($.projectTaskPerson.projectTask.in(ListUtil.toList((this.projectTaskDao.findAll(der)))));
		}
		if(IdUtil.isNotEmpty(projetTaskPersonId)){
			condition.and(this.$.projectTaskPerson.id.eq(projetTaskPersonId));
		}
		if (IdUtil.isNotEmpty(applyPersonId)) {
			condition.and($.applyPerson.id.eq(applyPersonId));
		}
		if (StringUtil.isNotEmpty(applyReason)) {
			condition.and($.applyReason.contains(applyReason));
		}
		if (IdUtil.isNotEmpty(checkPersonId)) {
			condition.and($.checkPerson.id.eq(checkPersonId));
		}
		if (StringUtil.isNotEmpty(checkComment)) {
			condition.and($.checkComment.contains(checkComment));
		}
		if (applyTimeBegin != null) {
			condition.and($.applyTime.after(applyTimeBegin));
		}

		if (applyTimeEnd != null) {
			condition.and($.applyTime.before(applyTimeEnd));
		}
		if (checkTimeBegin != null) {
			condition.and($.checkTime.after(checkTimeBegin));
		}

		if (checkTimeEnd != null) {
			condition.and($.checkTime.before(checkTimeEnd));
		}
		if (StringUtil.isNotEmpty(status)) {
			condition.and($.status.contains(status));
		}
		if (originalPlanFinishDateBegin != null) {
			condition.and($.originalPlanFinishDate
					.after(originalPlanFinishDateBegin));
		}

		if (originalPlanFinishDateEnd != null) {
			condition.and($.originalPlanFinishDate
					.before(originalPlanFinishDateEnd));
		}
		if (targetPlanFinishDateBegin != null) {
			condition.and($.targetPlanFinishDate
					.after(targetPlanFinishDateBegin));
		}

		if (targetPlanFinishDateEnd != null) {
			condition.and($.targetPlanFinishDate
					.before(targetPlanFinishDateEnd));
		}
		if (IdUtil.isNotEmpty(projectTaskId)) {
			condition.and($.projectTaskPerson.projectTask.id.eq(projectTaskId));
		}

		Sort sortObject = null;
		if (StringUtil.isEmpty(sortAttribute)) {
			sortObject = new Sort(Direction.DESC, "id");
		} else {
			sortObject = new Sort(Direction.fromStringOrNull(orderDirection),
					sortAttribute);
		}

		PageRequest pageRequest = new PageRequest(pageNumber - 1, pageSize,
				sortObject);
		return projectTaskDelayApplyDao.findAll(condition, pageRequest);
	}

	public void deleteProjectTaskDelayApply(Long id) {
		projectTaskDelayApplyDao.delete(id);
	}

	public void saveProjectTaskDelayApply(ProjectTaskDelayApply projectTaskDelayApply) {
		if(null == projectTaskDelayApply.getApplyTime()){
			projectTaskDelayApply.setApplyTime(DateUtil.nowDate());
		}

		//修改关联项目任务人员信息
		ProjectTaskPerson sourceProjectTaskPerson = this.projetTaskPersonDao.findOne(projectTaskDelayApply.getProjectTaskPerson().getId());
		sourceProjectTaskPerson.setStatus(projectTaskDelayApply.getStatus());
		
		this.projectTaskDelayApplyDao.save(projectTaskDelayApply);
		this.projetTaskPersonDao.save(sourceProjectTaskPerson);
	}

	public List<ProjectTaskDelayApply> findByStatus(People people, Long projectMemberType, String status) {
		BooleanBuilder condition = new BooleanBuilder();
		condition.and(this.$_projectMember.person.id.eq(people.getId()));
		condition.and(this.$_projectMember.projectMemberType.id.eq(projectMemberType));
		Iterable<ProjectMember> projectMembers = this.projectMemberDao.findAll(condition);
		Set<Long> ids = new HashSet<Long>();
		for (ProjectMember projectMember : projectMembers) {
			ids.add(projectMember.getProject().getId());
		}
		
		if (!ids.isEmpty()) {
			condition = new BooleanBuilder();
			condition.and(this.$_projectTask.project.id.in(ids));
			Iterable<ProjectTask> projectTasks = this.projectTaskDao.findAll(condition);
			ids.clear();
			for (ProjectTask projectTask : projectTasks) {
				ids.add(projectTask.getId());
			}
			
			if (!ids.isEmpty()) {
				condition = new BooleanBuilder();
				condition.and(this.$.projectTaskPerson.projectTask.id.in(ids));
				if (StringUtil.isNotEmpty(status)) {
					condition.and($.status.eq(status));
				}
				return ListUtil.toList(projectTaskDelayApplyDao.findAll(condition));
			}
		}
		return null;
	}

	public boolean checkProjectTaskDelayApply(ProjectTaskDelayApply projectTaskDelayApply) throws CannotUpdateException {
		ProjectTaskDelayApply sourceProjectTaskDelayApply = this.projectTaskDelayApplyDao.findOne(projectTaskDelayApply.getId());
		if(!ProcessStatus.DELAY_APPLY.equals(sourceProjectTaskDelayApply.getStatus())){
			throw new CannotUpdateException("您处理的项目任务延期申请已发生变化，请刷新后再操作！");
		}
		sourceProjectTaskDelayApply.setCheckPerson(projectTaskDelayApply.getCheckPerson());
		sourceProjectTaskDelayApply.setCheckTime(DateUtil.nowDate());
		sourceProjectTaskDelayApply.setCheckComment(projectTaskDelayApply.getCheckComment());
		sourceProjectTaskDelayApply.setStatus(projectTaskDelayApply.getStatus());
		
		//修改关联项目任务人员信息
		ProjectTaskPerson sourceProjectTaskPerson = sourceProjectTaskDelayApply.getProjectTaskPerson();
		sourceProjectTaskPerson.setStatus(projectTaskDelayApply.getProjectTaskPerson().getStatus());
		if(ProcessStatus.EXAMINE_SUCCESS.equals(projectTaskDelayApply.getStatus())){
			sourceProjectTaskPerson.setPlanFinishDate(sourceProjectTaskDelayApply.getTargetPlanFinishDate());
			sourceProjectTaskPerson.setPlanFinishDateChangeCount(sourceProjectTaskPerson.getPlanFinishDateChangeCount() + 1);
		}
		
		this.projetTaskPersonDao.save(sourceProjectTaskPerson);
		this.projectTaskDelayApplyDao.save(sourceProjectTaskDelayApply);
		return true;
	}

	public ProjectTaskDelayApply findOne(Long id) {
		return this.projectTaskDelayApplyDao.findOne(id);
	}

}
